package com.entertainment.ticketing.service;

import com.entertainment.ticketing.dto.UserDTO;
import com.entertainment.ticketing.dto.UserRegisterRequest;
import com.entertainment.ticketing.dto.UserUpdateProfileRequest;
import com.entertainment.ticketing.entity.UserInfo;
import com.entertainment.ticketing.repository.UserInfoRepository;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;

@Service
public class UserService {
    private final UserInfoRepository userRepo;
    private final PasswordEncoder passwordEncoder;

    public UserService(UserInfoRepository userRepo, PasswordEncoder passwordEncoder) {
        this.userRepo = userRepo;
        this.passwordEncoder = passwordEncoder;
    }

    public UserDTO register(UserRegisterRequest req) {
        if (userRepo.findByUsername(req.getUsername()).isPresent()) {
            throw new ResponseStatusException(org.springframework.http.HttpStatus.BAD_REQUEST, "用户名已存在");
        }
        if (userRepo.findByEmail(req.getEmail()).isPresent()) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "邮箱已注册");
        }
        UserInfo u = new UserInfo();
        u.setUsername(req.getUsername());
        u.setEmail(req.getEmail());
        u.setPassword(passwordEncoder.encode(req.getPassword()));
        u.setPhone(req.getPhone());
        u.setRealName(req.getRealName());
        u.setStatus((byte)1);
        u.setRole("USER");
        UserInfo saved = userRepo.save(u);
        return toDTO(saved);
    }

    public UserDTO updateProfile(Long userId, UserUpdateProfileRequest req) {
        UserInfo u = userRepo.findById(userId)
                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "用户不存在"));
        if (req.getEmail() != null && !req.getEmail().equals(u.getEmail())) {
            Optional<UserInfo> existingEmail = userRepo.findByEmail(req.getEmail());
            if (existingEmail.isPresent() && !existingEmail.get().getId().equals(userId)) {
                throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "邮箱已注册");
            }
            u.setEmail(req.getEmail());
        }
        if (req.getRealName() != null) {
            u.setRealName(req.getRealName());
        }
        if (req.getPhone() != null) {
            u.setPhone(req.getPhone());
        }
        if (req.getAvatarUrl() != null) {
            u.setAvatarUrl(req.getAvatarUrl());
        }
        UserInfo saved = userRepo.save(u);
        return toDTO(saved);
    }

    public UserDTO uploadAvatar(Long userId, MultipartFile file) {
        if (file == null || file.isEmpty()) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "请上传头像图片");
        }
        String contentType = file.getContentType();
        if (contentType == null || !contentType.startsWith("image/")) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "仅支持图片文件");
        }
        String original = file.getOriginalFilename();
        String ext = "";
        if (original != null && original.contains(".")) {
            ext = original.substring(original.lastIndexOf('.')).toLowerCase();
        }
        // 仅允许常见图片扩展名
        if (!(".png".equals(ext) || ".jpg".equals(ext) || ".jpeg".equals(ext) || ".webp".equals(ext))) {
            ext = ".png"; // 统一默认
        }
        try {
            // 统一使用相对工作目录下的 uploads/avatars 目录
            Path root = Paths.get("uploads", "avatars");
            Files.createDirectories(root);

            // 安全生成文件名，避免原始名中的特殊字符导致写入失败
            String safeBase = original != null ? original.replaceAll("[^a-zA-Z0-9._-]", "_") : "avatar";
            String filename = System.currentTimeMillis() + "_" + Math.abs(safeBase.hashCode()) + ext;
            Path target = root.resolve(filename);

            // 使用流写入，避免在部分环境下 MultipartFile#transferTo 的兼容性问题（Windows 临时文件等）
            try (java.io.InputStream in = file.getInputStream()) {
                java.nio.file.Files.copy(in, target, java.nio.file.StandardCopyOption.REPLACE_EXISTING);
            }

            String url = "/uploads/avatars/" + filename;

            UserInfo u = userRepo.findById(userId)
                    .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "用户不存在"));
            u.setAvatarUrl(url);
            UserInfo saved = userRepo.save(u);

            // 记录日志（log/yyyyMMddHHmmss.log）
            try {
                Path logDir = Paths.get("log");
                Files.createDirectories(logDir);
                String ts = new java.text.SimpleDateFormat("yyyyMMddHHmmss").format(new java.util.Date());
                Path logFile = logDir.resolve(ts + ".log");
                String line = "Avatar uploaded: userId=" + userId + ", file=" + target.toAbsolutePath() + System.lineSeparator();
                java.nio.file.Files.writeString(logFile, line, java.nio.file.StandardOpenOption.CREATE, java.nio.file.StandardOpenOption.APPEND);
            } catch (Exception ignore) {}

            return toDTO(saved);
        } catch (IOException e) {
            // 记录错误日志
            try {
                Path logDir = Paths.get("log");
                Files.createDirectories(logDir);
                String ts = new java.text.SimpleDateFormat("yyyyMMddHHmmss").format(new java.util.Date());
                Path logFile = logDir.resolve(ts + ".log");
                String line = "Avatar upload failed: userId=" + userId + ", err=" + e.getMessage() + System.lineSeparator();
                java.nio.file.Files.writeString(logFile, line, java.nio.file.StandardOpenOption.CREATE, java.nio.file.StandardOpenOption.APPEND);
            } catch (Exception ignore) {}
            throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "头像上传失败");
        }
    }

    public UserDTO getProfile(Long userId) {
        UserInfo u = userRepo.findById(userId)
                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "用户不存在"));
        return toDTO(u);
    }

    private UserDTO toDTO(UserInfo u) {
        return UserDTO.builder()
                .id(u.getId())
                .username(u.getUsername())
                .email(u.getEmail())
                .phone(u.getPhone())
                .realName(u.getRealName())
                .avatarUrl(u.getAvatarUrl())
                .status(u.getStatus())
                .role(u.getRole())
                .createdAt(u.getCreatedAt())
                .build();
    }

    public Long getUserIdByUsername(String username) {
        return userRepo.findByUsername(username).map(UserInfo::getId).orElse(null);
    }
}